package com.huahua.api.util;

import com.huahua.api.entity.developTool.github.dto.GitBranchesDTO;
import com.huahua.api.entity.developTool.github.vo.GithubObtainInfoVo;
import com.huahua.api.enums.GitBranchType;
import com.huahua.api.enums.GithubAddressTypeEnum;
import com.huahua.api.enums.LocalDirEnum;
import com.huahua.api.exception.CommonException;
import org.dromara.hutool.core.collection.CollStreamUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.CredentialsProvider;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

/**
 * @author huahua
 * GitHub 工具类
 */
public class OwnGithubUtil {

    /**
     * 判断GitHub地址是否合法，并根据不同类型的GitHub地址执行不同的逻辑
     *
     * @param url 要检查的GitHub URL
     * @return 返回URL是否为合法的GitHub地址
     */
    public static GithubObtainInfoVo obtainGithubUrlInfo(String url) {
        // 基本检查：确保输入是非空
        if (StrUtil.isEmpty(url)) {
            return GithubObtainInfoVo.error(url);
        }
        if (url.endsWith(".git")) {
            url = url.substring(0, url.length() - 4);
        }

        try {
            // 将输入转换为URL对象进行解析
            URL parsedUrl = new URL(url);

            // 检查是否为GitHub域名
            String hostname = parsedUrl.getHost();
            List<String> validHosts = Arrays.asList("github.com", "www.github.com", "raw.githubusercontent.com");
            if (!validHosts.contains(hostname)) {
                return GithubObtainInfoVo.error(url);
            }

            // 获取路径部分（去除域名和查询参数）
            String path = parsedUrl.getPath();
            if (path.startsWith("/")) {
                path = path.substring(1); // 移除开头的斜杠
            }

            String[] pathSegments = path.split("/");
            // 过滤掉空字符串
            List<String> segments = new java.util.ArrayList<>();
            for (String segment : pathSegments) {
                if (!segment.isEmpty()) {
                    segments.add(segment);
                }
            }

            // GitHub 仓库地址必须至少包含用户名和仓库名
            if (segments.size() < 2) {
                return GithubObtainInfoVo.error(url);
            }

            // 处理不同类型的GitHub URL
            // 1. 带分支的仓库地址 (github.com/username/repo/tree/branch)
            if (segments.size() >= 4 && segments.get(2).equals("tree")) {
                // 例如：获取用户名、仓库名和分支名
                String author = segments.get(0);
                String repoName = segments.get(1);
                String branchName = segments.get(3);

                // 在这里添加特定于带分支地址的逻辑
                System.out.println("处理带分支的仓库地址: " + author + "/" + repoName + ", 分支: " + branchName);
                return GithubObtainInfoVo.success(url, author, repoName, GithubAddressTypeEnum.HAS_BRANCH_REPOSITORY, branchName);

            }
            // 2. 带特定文件的仓库地址 (github.com/username/repo/blob/branch/path/to/file)
            else if (segments.size() >= 4 && segments.get(2).equals("blob")) {
                // TODO: 处理带特定文件的仓库地址
                // 例如：获取用户名、仓库名、分支名和文件路径
                String author = segments.get(0);
                String repoName = segments.get(1);
                String branchName = segments.get(3);

                // 构建文件路径
                StringBuilder filePath = new StringBuilder();
                for (int i = 4; i < segments.size(); i++) {
                    if (i > 4) {
                        filePath.append("/");
                    }
                    filePath.append(segments.get(i));
                }

                // 在这里添加特定于文件地址的逻辑
                System.out.println("处理文件地址: " + author + "/" + repoName +
                        ", 分支: " + branchName + ", 文件: " + filePath);
                return GithubObtainInfoVo.success(url, author, repoName, GithubAddressTypeEnum.HAS_BRANCH_FILE, branchName);
            }
            // 3. 发行版地址 (github.com/username/repo/releases/tag/version)
            else if (segments.size() >= 5 && segments.get(2).equals("releases") && segments.get(3).equals("tag")) {
                // TODO: 处理发行版地址
                // 例如：获取用户名、仓库名和版本标签
                String author = segments.get(0);
                String repoName = segments.get(1);
                String tagName = segments.get(4);

                // 在这里添加特定于发行版地址的逻辑
                System.out.println("处理发行版地址: " + author + "/" + repoName + ", 标签: " + tagName);
                return GithubObtainInfoVo.success(url, author, repoName, GithubAddressTypeEnum.RELEASES_URL);

            }
            // 4. 原始内容地址 (raw.githubusercontent.com/username/repo/branch/path/to/file)
            else if (hostname.equals("raw.githubusercontent.com") && segments.size() >= 3) {
                // TODO: 处理原始内容地址
                // 例如：获取用户名、仓库名、分支名和文件路径
                String author = segments.get(0);
                String repoName = segments.get(1);
                String branchName = segments.get(2);

                // 构建文件路径
                StringBuilder filePath = new StringBuilder();
                for (int i = 3; i < segments.size(); i++) {
                    if (i > 3) filePath.append("/");
                    filePath.append(segments.get(i));
                }
                // 在这里添加特定于原始内容地址的逻辑
                System.out.println("处理原始内容地址: " + author + "/" + repoName +
                        ", 分支: " + branchName + ", 文件: " + filePath);
                return GithubObtainInfoVo.success(url, author, repoName, GithubAddressTypeEnum.RELEASES_URL);
            }
            // 5. 基本仓库地址 (github.com/username/repo)
            else if (segments.size() == 2) {
                // TODO: 处理基本仓库地址
                // 例如：获取用户名和仓库名
                String author = segments.get(0);
                String repoName = segments.get(1);

                // 在这里添加特定于基本仓库地址的逻辑
                System.out.println("处理基本仓库地址: " + author + "/" + repoName);
                return GithubObtainInfoVo.success(url, author, repoName, GithubAddressTypeEnum.NO_BRANCH_REPOSITORY);
            }
            // 不符合已知的GitHub URL模式
            return GithubObtainInfoVo.error(url);
        } catch (MalformedURLException e) {
            // URL解析失败，不是有效的URL
            return GithubObtainInfoVo.error(url);
        }
    }

    /**
     * 根据仓库地址 和 分支名称 去获取带有分支的仓库地址
     */
    public static String getBranchUrl(String repositoryUrl, String branch) {
        GithubObtainInfoVo githubObtainInfoVo = obtainGithubUrlInfo(repositoryUrl);
        GithubAddressTypeEnum githubAddressTypeEnum = GithubAddressTypeEnum.toEnum(githubObtainInfoVo.getGithubAddressType());
        if (githubAddressTypeEnum == GithubAddressTypeEnum.NO_BRANCH_REPOSITORY) {
            return repositoryUrl + "/tree/" + branch;
        } else if (githubAddressTypeEnum == GithubAddressTypeEnum.HAS_BRANCH_REPOSITORY) {
            throw new CommonException("该仓库地址已经带有分支");
        } else {
            throw new CommonException("链接错误");
        }
    }


    public static String getDefaultBranch(String githubAddress) throws GitAPIException, IOException {
        Git git = initGit(githubAddress);
        String branch = git.getRepository().getBranch();
        GitUtils.closeGit(git);
        return branch;
    }


    public static List<String> getAllBranch(String githubAddress) throws GitAPIException, IOException {
        Git git = initGit(githubAddress);
        List<GitBranchesDTO> branches = GitUtils.getBranches(git, GitBranchType.REMOTE);
        GitUtils.closeGit(git);
        return CollStreamUtil.toList(branches, GitBranchesDTO::getBranchName);
    }

    public static Git initGit(String githubAddress) throws IOException, GitAPIException {
        CheckUtil.checkStrNotBlank(githubAddress, new RuntimeException("github地址不能为空"));
        String fileName = OwnFileUtil.getLastPath(githubAddress);
        CredentialsProvider credential = GitUtils.createCredentialsProvider("", "");
        String localPath = OwnFileUtil.getLocalPath(LocalDirEnum.GITHUB, fileName);
        Git git = GitUtils.getGit(githubAddress, credential, localPath);
        return git;
    }

    public static String genetateGithubDownloadUrl(GithubObtainInfoVo githubObtainInfoVo, String branch) {
        return StrUtil.format("https://github.com/{}/{}/archive/refs/heads/{}.zip", githubObtainInfoVo.getAuthor(), githubObtainInfoVo.getRepositoryName(), branch);
    }

    public static String removeSuffix(String githubAddress) {
        CheckUtil.checkStrNotBlank(githubAddress, new RuntimeException("github地址不能为空"));
        if (githubAddress.endsWith(".git")) {
            githubAddress = githubAddress.substring(0, githubAddress.length() - 4);
        }
        return githubAddress;
    }
}
